home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 4.iso / src / haeberli / mpeg / fs2.c < prev    next >
C/C++ Source or Header  |  1994-08-01  |  9KB  |  392 lines

  1. /*
  2.  * Copyright (c) 1992 The Regents of the University of California.
  3.  * All rights reserved.
  4.  * 
  5.  * Permission to use, copy, modify, and distribute this software and its
  6.  * documentation for any purpose, without fee, and without written agreement is
  7.  * hereby granted, provided that the above copyright notice and the following
  8.  * two paragraphs appear in all copies of this software.
  9.  * 
  10.  * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
  11.  * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
  12.  * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
  13.  * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  14.  * 
  15.  * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
  16.  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
  17.  * AND FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
  18.  * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
  19.  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
  20.  */
  21. #include "video.h"
  22. #include "dither.h"
  23. #include "fs2.h"
  24. #include "proto.h"
  25.  
  26. /* Structures for precomputed error propogation values. */
  27.  
  28. static FS2DithVal lum_index[256];
  29. static FS2DithVal cr_index[256];
  30. static FS2DithVal cb_index[256];
  31.  
  32.  
  33.  
  34. /*
  35.  *--------------------------------------------------------------
  36.  *
  37.  * InitFS2Dither --
  38.  *
  39.  *    Initializes structures for precomputed 2 error f-s dithering.
  40.  *      The value field of the structure contains the pixel component 
  41.  *      of the particular channel in question. Thus the addition of
  42.  *      the value field of a structure in the luminance index, a 
  43.  *      structure in the Cr index, and a structure in the Cb index will
  44.  *      yeild a color number. This color number can then be transformed
  45.  *      into a pixel value to be displayed. Each channel can then be
  46.  *      processed (i.e. dithered) separately, with the results being
  47.  *      added up and remapped to yield a final pixel value.
  48.  *
  49.  * Results:
  50.  *    None.
  51.  *
  52.  * Side effects:
  53.  *      None.
  54.  *
  55.  *--------------------------------------------------------------
  56.  */
  57.  
  58. void InitFS2Dither()
  59. {
  60.   int i;
  61.  
  62.   /* For each possible pixel value, precompute propogated error and
  63.      store in array.
  64.   */
  65.   
  66.   for (i=0; i<256; i++) {
  67.     lum_index[i].value = (i * LUM_RANGE) / 256;
  68.  
  69.     lum_index[i].e1 = (i-lum_values[lum_index[i].value]) / 2;
  70.     lum_index[i].e3 = (i - lum_values[lum_index[i].value]) - lum_index[i].e1;
  71.  
  72.     lum_index[i].value *= LUM_BASE;
  73.  
  74.     cr_index[i].value = (i * CR_RANGE) / 256; 
  75.  
  76.     cr_index[i].e1 = (i - cr_values[cr_index[i].value]) / 2;
  77.     cr_index[i].e3 = (i - cr_values[cr_index[i].value]) - cr_index[i].e1 ;
  78.  
  79.     cr_index[i].value *= CR_BASE;
  80.  
  81.     cb_index[i].value = (i * CB_RANGE) / 256; 
  82.  
  83.     cb_index[i].e1 = (i - cb_values[cb_index[i].value]) / 2;
  84.     cb_index[i].e3 = (i - cb_values[cb_index[i].value]) - cb_index[i].e1;
  85.  
  86.     cb_index[i].value *= CB_BASE;
  87.  
  88.   }
  89.  
  90. }
  91.  
  92.  
  93. /*
  94.  *--------------------------------------------------------------
  95.  *
  96.  * DitherImage --
  97.  *
  98.  *    Converts lum, cr, cb image planes into fixed colormap
  99.  *      space.
  100.  *
  101.  * Results:
  102.  *    the display plane is replaced by 8-bit colormap space
  103.  *      image.
  104.  *
  105.  * Side effects:
  106.  *      Hopefully, none.
  107.  *
  108.  *--------------------------------------------------------------
  109.  */
  110.  
  111. void FS2DitherImage(lum, cr, cb, disp, rows, cols)
  112.      unsigned char *lum, *cr, *cb, *disp;
  113.      int rows, cols;
  114. {
  115.   static char *cur_row_error, *next_row_error;
  116.   static int first = 1;
  117.   char  *cur_row_err_mark, *next_row_err_mark;
  118.   char *temp;
  119.   int i, j, pixsum, c_cols;
  120.   unsigned char *cur_row, *channel, *dest_row;
  121.   FS2DithVal *chan_index;
  122.  
  123.   /* Allocate error arrays. */
  124.  
  125.   if (first) {
  126.     cur_row_error = (char *) malloc(cols+2);
  127.     next_row_error = (char *) malloc(cols+2);
  128.     first = 0;
  129.   }
  130.  
  131.   /* Initialize error arrays. */
  132.  
  133.   memset(cur_row_error, 0, cols+2);
  134.   memset(next_row_error, 0, cols+2);
  135.  
  136.   /* Use luminance values first. */
  137.  
  138.   /* For each two rows, do... */
  139.  
  140.   for(i=0; i<rows; i+=2) {
  141.  
  142.     /* Establish pointer to current source and destination rows. */
  143.     cur_row = lum + (i*cols);
  144.     dest_row = disp + (i*cols);
  145.  
  146.     /* Establish pointers to error arrays. */
  147.     cur_row_err_mark = cur_row_error + 1;
  148.     next_row_err_mark = next_row_error + 1;
  149.  
  150.     
  151.     /* For each column within first row do... */
  152.  
  153.     for (j=0; j<cols; j++) {
  154.  
  155.       /* Calculate pixel value with error. */
  156.  
  157.       pixsum = *cur_row + *cur_row_err_mark;
  158.  
  159.       /* Bounds check. */
  160.       if (pixsum < 0) pixsum = 0;
  161.       else if (pixsum > 255) pixsum = 255;
  162.  
  163.       /* Establish dest value, propogate errors. */
  164.  
  165.       *dest_row = lum_index[pixsum].value;
  166.       *(cur_row_err_mark+1) += lum_index[pixsum].e1; 
  167.       *next_row_err_mark += lum_index[pixsum].e3; 
  168.  
  169.       /* Advance pointers. */
  170.  
  171.       cur_row++;
  172.       dest_row++;
  173.       cur_row_err_mark++;
  174.       next_row_err_mark++;
  175.     }
  176.  
  177.     /* Switch error arrays, so next row errors are now current row errors, and
  178.        vice versa. 
  179.     */
  180.  
  181.     temp = cur_row_error;
  182.     cur_row_error = next_row_error;
  183.     next_row_error = temp;
  184.  
  185.     /* Reset next row errors. */
  186.  
  187.     memset(next_row_error, 0, cols+2); 
  188.  
  189.     /* Establish pointers for second row. This one will be processed right to
  190.        left to establish serpantine motion.
  191.     */
  192.  
  193.     cur_row += cols-1;
  194.     dest_row += cols-1;
  195.     cur_row_err_mark = cur_row_error + cols;
  196.     next_row_err_mark = next_row_error + cols;
  197.  
  198.     /* Process each column... */
  199.  
  200.     for (j=0; j<cols; j++) {
  201.  
  202.       pixsum = *cur_row + *cur_row_err_mark;
  203.       if (pixsum < 0) pixsum = 0;
  204.       else if (pixsum > 255) pixsum = 255;
  205.       
  206.       *dest_row = lum_index[pixsum].value;
  207.       *(cur_row_err_mark-1) += lum_index[pixsum].e1; 
  208.       *next_row_err_mark += lum_index[pixsum].e3; 
  209.       
  210.       cur_row--;
  211.       dest_row--;
  212.       cur_row_err_mark--;
  213.       next_row_err_mark--;
  214.     }
  215.  
  216.     /* Switch error arrays. */
  217.  
  218.     temp = cur_row_error;
  219.     cur_row_error = next_row_error;
  220.     next_row_error = temp;
  221.  
  222.     /* Reset next row errors. */
  223.  
  224.     memset(next_row_error, 0, cols+2); 
  225.   }
  226.  
  227.   /* Reset error arrays. */
  228.  
  229.   memset(cur_row_error, 0, cols+2); 
  230.   
  231.   /* Establish column length divided by two. */
  232.  
  233.   c_cols = cols >> 1;
  234.  
  235.   /* Set channel to Cr. Use Cr index. */
  236.  
  237.   channel = cr;
  238.   chan_index = cr_index;
  239.   
  240.  repeat:
  241.  
  242.   /* Process each row of chrominance data... */
  243.  
  244.   for (i=0; i < rows; i+=2) {
  245.  
  246.     /* Establish pointers. */
  247.  
  248.     cur_row = channel + ((i>>1)*c_cols);
  249.     dest_row = disp + (i*cols);
  250.  
  251.     cur_row_err_mark = cur_row_error+1;
  252.     next_row_err_mark = next_row_error+1;
  253.  
  254.     /* For each column in row... */
  255.  
  256.     for (j=0; j<cols; j++) {
  257.       int p_val;
  258.  
  259.       /* Get pixel value as twos bit complement. */
  260.  
  261.       p_val = *cur_row;
  262.  
  263.       /* Add error term. */
  264.  
  265.       pixsum = *cur_row_err_mark + p_val;
  266.  
  267.       /* Bounds check. */
  268.  
  269.       if (pixsum < 0) pixsum = 0;
  270.       else if (pixsum > 255) pixsum = 255;
  271.  
  272.       /* Increment dest value. */
  273.  
  274.       *dest_row += chan_index[pixsum].value;
  275.  
  276.       /* Propogate error values. */
  277.  
  278.       *(cur_row_err_mark+1) += chan_index[pixsum].e1; 
  279.       *next_row_err_mark += chan_index[pixsum].e3; 
  280.  
  281.  
  282.       /* If count is odd, advance source pointer (Cr and Cb channels are 2:1 
  283.      subsampled.
  284.       */
  285.  
  286.       if (j&1) cur_row++;
  287.  
  288.       /* Advance destination and error pointers. */
  289.  
  290.       dest_row++;
  291.       cur_row_err_mark++;
  292.       next_row_err_mark++;
  293.     }
  294.  
  295.     /* Switch error arrays. */
  296.  
  297.     temp = cur_row_error;
  298.     cur_row_error = next_row_error;
  299.     next_row_error = temp;
  300.  
  301.     /* Reset next row errors. */
  302.  
  303.     memset(next_row_error, 0, cols+2);
  304.  
  305.     /* Re-establish pointers. */
  306.  
  307.     cur_row += c_cols-1;
  308.     dest_row += cols-1;
  309.     cur_row_err_mark = cur_row_error+cols;
  310.     next_row_err_mark = next_row_error+cols;
  311.  
  312.     /* Process second row right to left. */
  313.  
  314.     for (j=0; j<cols; j++) {
  315.       int p_val;
  316.  
  317.       /* Get source value as twos bit complement. */
  318.  
  319.       p_val = *cur_row;
  320.  
  321.       /* Add error. */
  322.  
  323.       pixsum = *cur_row_err_mark + p_val;
  324.  
  325.       /* Bounds check. */
  326.  
  327.       if (pixsum < 0) pixsum = 0;
  328.       else if (pixsum > 255) pixsum = 255;
  329.  
  330.       /* Increment dest value. */
  331.  
  332.       *dest_row += chan_index[pixsum].value;
  333.  
  334.       /* Propogate errors. */
  335.  
  336.       *(cur_row_err_mark-1) += chan_index[pixsum].e1; 
  337.       *next_row_err_mark += chan_index[pixsum].e3; 
  338.  
  339.       /* If column counters is odd, decrement source pointer. */
  340.  
  341.       if (j&1) cur_row--;
  342.  
  343.       /* Decrement dest and error pointers. */
  344.  
  345.       dest_row--;
  346.       cur_row_err_mark--;
  347.       next_row_err_mark--;
  348.     }
  349.  
  350.     /* Switch error arrays. */
  351.  
  352.     temp = cur_row_error;
  353.     cur_row_error = next_row_error;
  354.     next_row_error = temp;
  355.  
  356.     /* Reinitialize next row errors. */
  357.  
  358.     memset(next_row_error, 0, cols+2);
  359.   }
  360.  
  361.   /* If Cr channel completed, set channel to Cb and Cb index and repeat. */
  362.  
  363.   if (channel == cr) {
  364.     channel = cb;
  365.     chan_index = cb_index;
  366.     memset(cur_row_error, 0, cols+2);
  367.  
  368.     goto repeat;
  369.   }
  370.  
  371.   /* Establish pointer to start of display frame. */
  372.  
  373.   dest_row = disp;
  374.  
  375.   /* Transform all display values to pixel values. */
  376.  
  377.   for (i=0; i<rows; i++) {
  378.     for (j=0; j<cols; j++) {
  379.       *dest_row =  pixel[*dest_row];
  380.       dest_row++;
  381.     }
  382.   }
  383. }
  384.  
  385.  
  386.  
  387.  
  388.  
  389.  
  390.  
  391.  
  392.